package controllers

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"net/http"
	"net/smtp"
	"strconv"
	"strings"
	"time"

	"github.com/astaxie/beego"
)

type MailController struct {
	beego.Controller
}

var EmailVerifyCode map[string]Code

type Code struct {
	Value   string
	Expires int64
}

func (this *MailController) SendPWDResetMail() {
	// var username, email string
	// this.Ctx.Input.Bind(&username, "username")
	// this.Ctx.Input.Bind(&email, "email")

	reqBody := this.Ctx.Input.RequestBody
	var reqMap map[string]string
	err := json.Unmarshal(reqBody, &reqMap)

	if err != nil {
		this.Ctx.Output.Status = http.StatusInternalServerError
		this.Ctx.Output.Body([]byte(err.Error()))
		return
	}

	mobile := reqMap["mobile"]
	email := reqMap["email"]

	if mobile == "" || email == "" {
		this.Ctx.Output.Status = http.StatusInternalServerError
		this.Ctx.Output.Body([]byte("手机号和邮箱必填"))
		return
	}

	mail := Mail{}
	mail.senderId = "passwd_reset@163.com"
	mail.toIds = []string{email}
	mail.subject = "密码重置邮件"

	resetURL := beego.AppConfig.String("resetPwdURL")
	ts := strconv.FormatInt(time.Now().Unix(), 10)

	mail.body = "北京西大校友产业生态圈联盟系统重置密码\n\n点击此链接完成重置 " + resetURL + "?mobile=" + mobile + "&ts=" + ts

	messageBody := mail.BuildMessage()

	smtpServer := SmtpServer{host: "smtp.163.com", port: "465"}

	beego.Info(smtpServer.host)
	//build an auth
	auth := smtp.PlainAuth("", mail.senderId, "Pa88w0rd", smtpServer.host)

	// Gmail will reject connection if it's not secure
	// TLS config
	tlsconfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         smtpServer.host,
	}

	conn, err := tls.Dial("tcp", smtpServer.ServerName(), tlsconfig)
	if err != nil {
		beego.Error(err)
		this.Ctx.Output.Status = http.StatusInternalServerError
		this.Ctx.Output.Body([]byte(err.Error()))
	}

	client, err := smtp.NewClient(conn, smtpServer.host)
	if err != nil {
		beego.Error(err)
		this.Ctx.Output.Status = http.StatusInternalServerError
		this.Ctx.Output.Body([]byte(err.Error()))
	}

	// step 1: Use Auth
	if err = client.Auth(auth); err != nil {
		beego.Error(err)
		this.Ctx.Output.Status = http.StatusInternalServerError
		this.Ctx.Output.Body([]byte(err.Error()))
	}

	// step 2: add all from and to
	if err = client.Mail(mail.senderId); err != nil {
		beego.Error(err)
	}
	for _, k := range mail.toIds {
		if err = client.Rcpt(k); err != nil {
			beego.Error(err)
			this.Ctx.Output.Status = http.StatusInternalServerError
			this.Ctx.Output.Body([]byte(err.Error()))
		}
	}

	// Data
	w, err := client.Data()
	if err != nil {
		beego.Error(err)
	}

	_, err = w.Write([]byte(messageBody))
	if err != nil {
		beego.Error(err)
	}

	err = w.Close()
	if err != nil {
		beego.Error(err)
	}
	client.Quit()
	beego.Info("Mail sent successfully")
	this.Ctx.Output.Status = http.StatusOK
	this.Ctx.Output.Body([]byte("Mail sent successfully"))
	return
}

type Mail struct {
	senderId string
	toIds    []string
	subject  string
	body     string
}

type SmtpServer struct {
	host string
	port string
}

func (s *SmtpServer) ServerName() string {
	return s.host + ":" + s.port
}

func (mail *Mail) BuildMessage() string {
	message := ""
	message += fmt.Sprintf("From: %s\r\n", mail.senderId)
	if len(mail.toIds) > 0 {
		message += fmt.Sprintf("To: %s\r\n", strings.Join(mail.toIds, ";"))
	}

	message += fmt.Sprintf("Subject: %s\r\n", mail.subject)
	message += "\r\n" + mail.body

	return message
}
